package panda.server.util.datamine;

import java.io.File;
import java.util.Scanner;

/**
 * Mines the following data from Magic Workstation text spoilers:<br>
 * .Card Name<br>
 * .Card Color<br>
 * .Mana Cost<br>
 * .Type & Class<br>
 * .Pow/Tou<br>
 * .Card Text<br>
 * .Flavor Text<br>
 * .Artist<br>
 * .Rarity<br>
 * .Card #<br>
 * <br>
 * This class mines Gatherer's "text spoiler" for card information. Intended for use before magiccards.info uploads full
 * HQ scans and full card information.<br>
 * <br>
 * There are several formatting issues with the Shards of Alara spoiler text file released for Magic Workstation:<br>
 * .newlines before the Artist line. Fix by replacing \n\nA with \nA in metapad.<br>
 * .newlines before the Flavor Text line. Fix by replacing \n\nF with \nF in metapad.<br>
 * ...actually, newlines just about everywhere :/
 * .Lands are common. Fix by selecting all 20 basic lands and replacing "C" with "L".<br>
 * .Mythic Rares are represented as Rares. Fix using linear search of all MR cards and changing their rarity to "MR"<br>
 * 
 * @author zane.tian@gmail.com
 */
public class MagicWorkStationOracleMiner {
	public static void main(String[] args) {
		createMagicCardsFromSpoiler();
	}

	/**
	 * Reads Magic Workstation oracle spoilers to create java code that initializes MagicCard objects.<br>
	 * In order to get the text file from the text file, paste the text spoiler into a text editor and replace all TABs
	 * with spaces and then replace all double spaces with spaces. Card data should now be split by a blank new line.
	 * There are issues with artist names not being all on one line after this.
	 */
	private static void createMagicCardsFromSpoiler() {
		try {
			/* TODO: why not UTF8? */
            /* note that IDEA requires an extra parent folder for some reason :| */
			Scanner scanner = new Scanner(new File("src/panda/cardutil/data/conflux-mws-spoiler.txt"), "ISO-8859-1");

			String cardName;
			String castingCost;
			String type;
			String pwrtgh;
			String rulesText;
			String flavorText;
			String rarity;
			String artist;
			String cardDelimiter;
			int id;

			StringBuffer code = new StringBuffer();

			/**
			 * Card Name: Akrasan Squire<br>
			 * Card Color: W<br>
			 * Mana Cost: W<br>
			 * Type & Class: Creature - Human Soldier<br>
			 * Pow/Tou: 1/1<br>
			 * Card Text: Exalted (Whenever a creature you control attacks alone, that creature gets +1/+1 until...)<br>
			 * Flavor Text: Bant's armies are primarily composed of members of the Mortar caste... <br>
			 * Artist: Todd Lockwood<br>
			 * Rarity: C<br>
			 * Card #: 1/249<br>
			 */

			while(scanner.hasNext()) {
				
				/* Card Name: Akrasan Squire */
				String nameLine[] = scanner.nextLine().split(": ");
				assert nameLine[0].equals("Card Name");
				cardName = nameLine[1];
				
				/* Card Color: W *//** we ignore this line but at least check if it's the right type of line */
				String colorLine[] = scanner.nextLine().split(": ");
				assert colorLine[0].equals("Card Color");

				/*  Mana Cost: W */
				String costLine[] = scanner.nextLine().split(": ");
				assert costLine[0].equals("Mana Cost");
				castingCost = costLine.length == 2 ? costLine[1] : "";

				/* Type & Class: Creature - Human Soldier */
				String typeLine[] = scanner.nextLine().split(": ");
				assert typeLine[0].equals("Type & Class");
				type = typeLine[1];

				/* Pow/Tou: 1/1 *//** planeswalkers use "//x" where x is their starting loyalty */
				String powerLine[] = scanner.nextLine().split(": ");
				assert powerLine[0].equals("Pow/Tou");
				pwrtgh = powerLine.length == 2? powerLine[1] : "";

				/* Card Text: Exalted (Whenever a creature you control attacks alone, that creature gets +1/+1 until...) */
				/** logic is a bit different here because we need to account for ": " occuring in the rules text */
				String rulesLine = scanner.nextLine();
				int delimiterPosition = rulesLine.indexOf(": ");
				assert rulesLine.substring(0, delimiterPosition).equals("Card Text");
				
				rulesText = rulesLine.substring(delimiterPosition + 2);
				
				
				/* Flavor Text: Bant's armies are primarily composed of members of the Mortar caste... */
				String flavorLine[] = scanner.nextLine().split(": ");
				assert flavorLine[0].equals("Flavor Text");
				flavorText = flavorLine.length == 2 ? flavorLine[1] : "";
				
				/* Artist: Todd Lockwood */
				String artistLine[] = scanner.nextLine().split(": ");
				assert artistLine[0].equals("Artist");
				artist = artistLine.length == 2 ? artistLine[1] : "no data";

				/* Rarity: C */
				String rarityLine[] = scanner.nextLine().split(": ");
				assert rarityLine[0].equals("Rarity");

				String rareToken = rarityLine[1];

				if(rareToken.equals("MR")) {
					rarity = "Mythic Rare";
				} else if(rareToken.equals("R")) {
					rarity = "Rare";
				} else if(rareToken.equals("U")) {
					rarity = "Uncommon";
				} else if(rareToken.equals("C")) {
					rarity = "Common";
				} else if(rareToken.equals("L")) {
					rarity = "Basic Land";
				} else {
					rarity = "error :P";
					assert false : "Card: " + cardName + " is not one of the defined rarity types";
				}

				/* Card #: 1/249 */
				String numberLine[] = scanner.nextLine().split(": ");
				assert numberLine[0].equals("Card #");
				
				
				String idString = numberLine[1].split("/")[0];
				id = Integer.parseInt(idString);
				
				/**
				 * output java code to instantiate a MagicCard: public MagicCard(MagicSet set, String name, String
				 * castingCost, String type, String bodyText, CardRarity rarity, String illustrator, int id)
				 */
				code.delete(0, code.length());

				code.append("cards.add(new MagicCard(set, \"");
				code.append(cardName);
				code.append("\", \"");
				code.append(castingCost);
				code.append("\", \"");

				if(pwrtgh.equals("")) {
					code.append(type);
				} else {
					code.append(type + " " + pwrtgh);
				}

				code.append("\", \"");
				code.append(rulesText.replace("\"", "\\\"")); /* Some cards have quotes in their rules text. Must sanitize */
				if(flavorText.equals("")) {
					/** do nothing extra */
				} else {
					// code.append("<br>" + flavorText.replace("\"", "\\\""));
				}
				code.append("\", ");

				if(rarity.equals("Mythic Rare")) {
					code.append("CardRarity.MYTHIC");
				} else if(rarity.equals("Rare")) {
					code.append("CardRarity.RARE");
				} else if(rarity.equals("Uncommon")) {
					code.append("CardRarity.UNCOMMON");
				} else if(rarity.equals("Common")) {
					code.append("CardRarity.COMMON");
				} else if(rarity.equals("Basic Land")) {
					code.append("CardRarity.LAND");
				} else {
					throw new IllegalStateException("CardRarity was not properly defined: " + rarity);
				}

				code.append(", \"");
				code.append(artist);
				code.append("\", ");
				code.append(id);
				code.append("));");

				//System.out.println(code);
				
				/** generate the correct (name, id) pairs in a hashmap since Gatherer doesn't provide IDs */
				/** used to fix GathererOracleMiner */
				System.out.println("nameIdMap.put(\"" + cardName + "\", " + id + ");");

				/** Each card information block is separated by a blank line with 3 spaces */
				/** Check for end of file: text spoilers end when there is no 3 space separator line */
				if(scanner.hasNext()) {
					cardDelimiter = scanner.nextLine();
					assert cardDelimiter.equals("");
				} else {
					break;
				}

			}
		} catch(Exception ex) {
			ex.printStackTrace();
		}
	}
}